/********************************************************************
*                                                                   *
* Microsoft Windows Sidebar Gadget for NNTT.ORG                     *
* Released under the MIT license by Alexey Glukharev, Januar 2012.  *
*                                                                   *
********************************************************************/

//----------------------------------------
// PersistentSettings
//----

// Constructor
PersistentSettings = function () {
    var self = this;
    
    // Путь для хранения настроек виджета
    self.g_path = "HKCU\\Software\\NNTTInformer\\settings";
    
    // Пытаемся создать ссистемный объект для доступа к реестру
    try {
        self.g_shell = new ActiveXObject("WScript.Shell");
    }
    catch (e) {
        System.Debug.outputString("NNTT.ORG Informer: Unable to create 'WScript.Shell' object. Reason: " + e.description);
    }
    
    return self;
};

// Methodes
PersistentSettings.prototype = {
    write: function (value) {
        var self = this;
        
        if (typeof (value) == 'undefined' || value == null) {
            return false;
        }
        
        value = value.trim();
        if (value.length == 0) {
            return false;
        }
        
        // Try to write registry key
        if (typeof (self.g_shell) != 'undefined' && self.g_shell != null) {
            try {
                self.g_shell.RegWrite(self.g_path, value, "REG_SZ");
                return true;
            }
            catch (e) {
                System.Debug.outputString("NNNTT.ORG Informer: Unable to write registry key '" + self.g_path + "', value '" + value + "'. Reason: " + e.description);
            }
        }
        
        return false;
    },
    read: function () {
        var self = this;
        var value = "";
        
        // Try to read registry key
        if (typeof (self.g_shell) != 'undefined' && self.g_shell != null) {
            try {
                value = self.g_shell.RegRead(self.g_path);
                value = value.trim();
            }
            catch (e) {
                System.Debug.outputString("NNTT.ORG Informer: Unable to read registry key '" + self.g_path + "'. Reason: " + e.description);
            }
        }
        
        return value;
    }
};

//----------------------------------------
// ProfileManager
//----

// Constructor
ProfileManager = function (profilesList) {
    var self = this;
    self.g_list = profilesList;
    
    self.g_defaults = {
        name: "",
        client: "",
        protocol: "http",
        host: "localhost",
        port: "",
        user: "",
        password: ""
    };
    
    return self;
};

// Methodes
ProfileManager.prototype = {
    // Add new profile
    add: function (options) {
        var self = this;
        var opt = new Object();
        
        // Verify argument
        if (typeof (options) == 'undefined' || options == null) {
            throw new Error("Bad argument");
        }
        
        // Merge options
        // To keep the correct set of properties we will update only the known properties
        for (var i in self.g_defaults) {
            if (typeof (options[i]) != 'undefined') {
                opt[i] = options[i];
            } else {
                opt[i] = self.g_defaults[i];
            }
        }
        
        self.g_list.push(opt);
    },
    
    // Get existing profile
    get: function (name) {
        var self = this;
        
        // Verify argument
        if (typeof (name) == 'undefined' || name == null) {
            throw new Error("Bad argument");
        }
        
        name = name.trim();
        if (name.length == 0) {
            throw new Error("Profile name is empty");
        }
        
        for (var i = 0; i < self.g_list.length; i++) {
            if (self.g_list[i].name == name) {
                return copy(self.g_list[i]);
            }
        }
        
        // Profile with that name was not found
        throw new Error("Profile with name '" + name + "' was not found.");
    },
    
    // Remove existing profile
    remove: function (name) {
        var self = this;
        
        // Verify argument
        if (typeof (name) == 'undefined' || name == null) {
            throw new Error("Bad argument");
        }
        
        name = name.trim();
        if (name.length == 0) {
            throw new Error("Profile name is empty");
        }
        
        for (var i = 0; i < self.g_list.length; i++) {
            if (self.g_list[i].name == name) {
                self.g_list.splice(i, 1);
                break;
            }
        }
    },
    
    // Check if profile exist
    isExist: function (name) {
        var self = this;
        
        // Verify argument
        if (typeof (name) == 'undefined' || name == null) {
            throw new Error("Bad argument");
        }
        
        name = name.trim();
        if (name.length == 0) {
            throw new Error("Profile name is empty");
        }
        
        for (var i = 0; i < self.g_list.length; i++) {
            if (self.g_list[i].name == name) {
                return true;
            }
        }
        
        // Profile with that name was not found
        return false;
    },
    
    // Return array of available profiles
    getProfilesList: function () {
        var self = this;
        var ret =[];
        
        for (var i = 0; i < self.g_list.length; i++) {
            ret.push(self.g_list[i].name);
        }
        
        return ret;
    }
};

//----------------------------------------
// Settings singleton class
//----

function Settings() {
    if (typeof (arguments.callee.instance) == 'undefined') {
        // Constructor
        arguments.callee.instance = new function () {
            
            //----------------------------------------
            // Members
            //----
            
            // Settings object
            var options = {
                // Search type in a decked state
                defaultSearchType: "http://www.nntt.org/tracker.php",
                
                // Period of data updates
                // Default - every 10 minutes
                dataRefreshPeriod: "600",
                
                // Period of panels change
                // By default - every minute
                panelsTogglePeriod: "60",
                
                // The time period for which the news is highlighted
                // Default - 1 day
                lastNewsPeriod: "86400",
                
                // Client statistic tame period
                // Default - 1 minute
                statisticPeriod: "60",
                
                // Default startup panel
                startupPanel: "news",
                
                // List of forums, for which is requested release
                forumsList:[],
                
                // Torrent profiles array
                torrentProfiles:[],
                
                // Used torrent profile
                defaultProfile: ""
            };
            
            // Data stream object
            var stream = new PersistentSettings();
            
            //----------------------------------------
            // Methodes
            //----
            
            // Return value of option 'name'
            this.get = function (name) {
                if (typeof (name) == 'undefined' || name == null) {
                    throw new Error("Bad property");
                }
                
                if (typeof (options[name]) == 'undefined') {
                    throw new Error("Unknown property '" + name + "'");
                }
                
                return options[name];
            };
            
            // Set 'value' of option 'name'
            this.set = function (name, value) {
                if (typeof (name) == 'undefined' || name == null) {
                    throw new Error("Bad property");
                }
                
                if (typeof (options[name]) == 'undefined') {
                    throw new Error("Unknown property '" + name + "'");
                }
                
                if (typeof (value) == 'undefined' || value == null) {
                    throw new Error("Bad value");
                }
                
                options[name] = value;
            };
            
            // Serialize settings in persistent storage
            this.save = function () {
                var data = JSON.stringify(options, function (key, value) {
                    if (key == 'password') {
                        try {
                            return Crypto.AES.encrypt(value, System.Environment.machineName);
                        }
                        catch (e) {
                            System.Debug.outputString("NNTT.ORG Informer: Unable to encrypt string. Reason: " + e.description);
                            return ""; // Avoid unprotected password writing
                        }
                    }
                    return value;
                });
                
                return stream.write(data);
            };
            
            // Restore settings from persistent storage
            this.read = function () {
                var data = stream.read();
                
                // JSON parser break down if string is empty
                if (data.length > 0) {
                    // JSON.parse can throw a SyntaxError exception.
                    try {
                        var opt = JSON.parse(data, function (key, value) {
                            if (key == 'password') {
                                try {
                                    return Crypto.AES.decrypt(value, System.Environment.machineName);
                                }
                                catch (e) {
                                    System.Debug.outputString("NNTT.ORG Informer: Unable to decrypt string. Reason: " + e.description);
                                    
                                    // Password has not been decrypted
                                    // It makes no sense to send it that way
                                    // So return an empty string
                                    return "";
                                }
                            }
                            
                            return value;
                        });
                        
                        // Merge the settings
                        // To keep the correct set of properties we will update only the known properties
                        for (var i in options) {
                            if (typeof (opt[i]) != 'undefined') {
                                options[i] = opt[i];
                            }
                        }
                    }
                    catch (e) {
                        System.Debug.outputString("NNTT.ORG Informer: Unable to parse settings data. Reason: " + e.description);
                    }
                }
            };
            
            // Get new profile manager instance
            this.getProfileManager = function () {
                return new ProfileManager(options.torrentProfiles);
            }
            
            // Initial options reading
            this.read();
        };
    }
    
    return arguments.callee.instance;
}